
use std::env;
use std::fs;
use std::str::FromStr;

mod matrix_file_reader;
mod simulator;

use matrix_file_reader::Konfidenzmatrix;

fn main() -> Result<(), &'static str>{
    println!("KoMa-Simulator: Ein Simulator für probabilistische Konfidenzmatrizen");
    let mut kommandozeile: Vec<String> = env::args().collect();
    let mut matrix_datei: Result<String, &'static str> = Err("Fehler: keine Datei angegeben");
    let mut tatsaechlich_wahl: Result<bool, &'static str> = Err("Fehler: keine tatsächliche Wahl angegeben");
    kommandozeile.reverse();
    let ich: String = match kommandozeile.pop() {
        Some(x) => { x },
        None => { "Programm".to_string() },
    };
    
    let _ = loop {
        let akt_argument =
            match kommandozeile.pop() {
                Some(x) => { x },
                None => { break "" },
            };
        
        if akt_argument == "--matrix-datei" || akt_argument == "-m" {
            matrix_datei = verifiziere_matrixdatei(kommandozeile.pop());
        } else if akt_argument == "--wahl" {
            tatsaechlich_wahl = verifiziere_wahl(kommandozeile.pop());
        }
    };

    if matrix_datei.is_err() {
        aufrufshilfe(&ich);
        match matrix_datei.clone().err() {
            Some(e) => { return Err(e); },
            None => { () },
        }
    } 
    
    if tatsaechlich_wahl.is_err() {
        aufrufshilfe(&ich);
        match tatsaechlich_wahl.clone().err() {
            Some(e) => { return Err(e); },
            None => { () },
        }
    }


    let mat: Result<Konfidenzmatrix<f32>, &'static str> = matrix_file_reader::lese_matrix_datei(matrix_datei.unwrap());
    if mat.is_err() {
        match mat.clone().err() {
            None => { () },
            Some(n) => {
                return Err(n);
            },
        }
    }
    
    match simulator::simuliere(mat.unwrap(), tatsaechlich_wahl.unwrap()) {
        Err(x) => { Err(x) },
        Ok(k) => {
            println!("Ergebnis der Simulation: {}", k);
            Ok(())
        }
    }
}

fn verifiziere_wahl(wahlargument: Option<String>) -> Result<bool, &'static str> {
    match wahlargument {
        Some(x) => {
            match bool::from_str(&x) {
                Ok(w) => Ok(w),
                Err(_b) => Err("Fehler: Ungültiger Wahrheitswert"),
            }
        },
        None => {
            return Err("Fehler: Kein Wahrheitswert angegeben!");
        }
    }
}

fn verifiziere_matrixdatei(dateiargument: Option<String>) -> Result<String, &'static str> {
    let matrix_datei = match dateiargument {
        Some(x) => { x },
        None => {
            return Err("Fehler: Keine Datei angegeben!");
        },
    };
    
    
    match fs::metadata(&matrix_datei) {
        Err(_k) => {
            Err("Fehler: die angegebene Datei kann nicht gefunden werden!")
        },
        Ok(k) => {
            if ! k.is_file() {
                Err("Fehler: die angegebene Datei kann nicht gefunden werden!")
            } else {
                Ok(matrix_datei)
            }            
        }        
    }
}

fn aufrufshilfe(ich: &String) {
    println!("Aufruf:");
    println!("{} <optionen>", *ich);
    println!("");
    println!("--matrix-datei [DATEI] | -m [DATEI]\tDatei mit Konfidenzmatrix angeben");
    println!("--wahl [true|false]\tTatsächlichen Zweig zum Simulieren angeben");
    println!("");
}
